#define _CRT_SECURE_NO_WARNINGS
#include"string.h"
namespace bit {

	const size_t string::npos = -1;


	string::iterator string::begin()
	{
		return &(this->_str[0]);
	}
	string::iterator string::end()
	{
		return &(this->_str[_size]);
	}
	string::const_iterator string::begin() const
	{
		return &(this->_str[0]);
	}
	string::const_iterator string::end() const
	{
		return &(this->_str[_size]);
	}

	string::string(const char* str)
		:_size(strlen(str))
	{
		_str = new char[_size + 1];
		strcpy(_str, str);
		_capacity = _size;
	}
	string::string(const string& s)
		:_size(s.size())
	{
		_str = new char[_size + 1];
		strcpy(_str, s._str);
		_capacity = _size;
	}

	string& string::operator=(const string& s)
	{
		/*_capacity = s.capacity();
		_size = s.size();
		_str = new char[]*/
		this->resereve(s.capacity());
		strcpy(_str, s.c_str());
		return *this;
	}

	string::~string()
	{
		delete[] _str;
	}

	size_t string::size()const
	{
		return _size;
	}
	size_t string::capacity()const
	{
		return _capacity;
	}


	const char* string::c_str()const
	{
		return _str;
	}
	char& string::operator[](size_t pos)
	{
		return *(_str + pos);
	}
	const char& string::operator[](size_t pos)const
	{
		return *(_str + pos);
	}
	void string::resereve(size_t newcapacity)
	{
		bit::string str(_str);
		delete[] _str;
		_capacity = newcapacity;
		_str = new char[_capacity + 1];
		strcpy(_str, str.c_str());
	}
	void string::push_back(char ch)
	{
		if (_size == _capacity)
		{
			size_t newcapcity = _capacity == 0 ? 4 : 2 * _capacity;
			resereve(newcapcity);
		}
		_str[_size++] = ch;
		_str[_size] = '\0';
	}
	void string::append(const char* str)
	{
		/*size_t len = strlen(str);
		while(_size + len >= _capacity)
		{
			size_t newcapcity = _capacity == 0 ? 4 : 2 * _capacity;
			resereve(newcapcity);
		}
		strcpy(_str + _size, str);*/
		/*for (int i = 0; i < len; i++)
		{
			this->push_back(str[i]);
		}*/
		this->insert(_size, str);
	}

	string& string::operator+=(char ch)
	{
		this->push_back(ch);
		return *this;
	}
	string& string::operator+=(const char* str)
	{
		this->append(str);
		return *this;
	}

	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			size_t newcapcity = _capacity == 0 ? 4 : 2 * _capacity;
			resereve(newcapcity);
		}

		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			end--;
		}
		_str[pos] = ch;

	}
	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			resereve(_size + len);
		}
		//size_t end = _size + len;
		//while (end > pos + len - 1)
		//{
		//	_str[end] = _str[end - len];
		//	--end;
		//}
		size_t end = _size + len;
		while (end >= pos + len)
		{
			_str[end] = _str[end - len];
			end--;
		}

		memcpy(_str + pos, str, len);
		_size += len;
	}
	void string::erase(size_t pos, size_t len)
	{
		if (len >= _size - pos)
		{
			_str[pos] = '\0';
		}
		else
		{
			char* str = _str + pos + len;
			strcpy(_str + pos, str);
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (int i = pos; i < this->size(); i++)
		{
			if (_str[i] == ch)
			{
				return i;
			}
		}
		return npos;
	}
	size_t string::find(const char* str, size_t pos)
	{
		char* p = strstr(_str, str);
		return p - _str;
	}

	void string::swap(string& s)
	{
		char* tmp = this->_str;
		this->_str = s._str;
		s._str = tmp;
	}
	string string::substr(size_t pos, size_t len)
	{
		if (len > _size - pos)
		{
			return _str + pos;
		}
		else
		{
			string str;
			for (int i = 0; i < len; i++)
			{
				str.push_back(_str[pos + i]);
			}
			return str;
		}

	}


	bool string::operator<(const string& s) const
	{
		return !(*this >= s);
	}
	bool string::operator>(const string& s) const
	{
		return strcmp(this->c_str(), s.c_str()) > 0;
	}
	bool string::operator<=(const string& s) const
	{
		return !(*this > s);
	}
	bool string::operator>=(const string& s) const
	{
		if (this->operator>(s) && this->operator==(s))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	bool string::operator==(const string& s) const
	{
		return strcmp(this->c_str(), s.c_str()) == 0;
	}
	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}
	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}


	std::istream& operator>> (std::istream& is, string& str)
	{
		
		char ch = is.get();
		while (ch != ' ' && ch != '\n')
		{
			str.push_back(ch);
			ch = is.get();
		}

		return is;
	}
	std::ostream& operator<< (std::ostream& os, const string& str)
	{
		os << str.c_str();
		return os;
	}

}
